package KeyBoardMap;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class CorpusIndexer extends Thread {

	private Map<Character, Double> probabilityMap = null;
	private Map<Character, Double> unsupported = null;
	private int charAmount;
	private int unsupportedCharAmount;
	private int numOfFiles;
	private int numOfDirs;
	private String dirName;
	private boolean done;

	private CorpusIndexer() {
		probabilityMap = new HashMap<Character, Double>();
		unsupported = new HashMap<Character,Double>();
		charAmount=0;
		numOfFiles=0;
		numOfDirs=0;
		unsupportedCharAmount =0;
		done = false;
	}

	public CorpusIndexer(String charMApFileName,String CorpusLocation) {
		this();
		this.dirName = new String (CorpusLocation);
		Properties p = new Properties();
		try {
			p.load(new FileInputStream(charMApFileName));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		for (Object o : p.keySet()) {
//			System.out.println("key: "+o+" val "+p.get(o));
			this.probabilityMap.put(((String) o).charAt(0), 0.0);
			
		}
//		System.out.println(this.probabilityMap.keySet());

	}
	
	

	public void run() {
		System.out.println(loadCorpusDir());
		done = true;
		System.out.println(charAmount);
		System.out.println(unsupportedCharAmount);
		System.out.println(probabilityMap.size());
		System.out.println(unsupported.size());
		System.out.println("done");
	}

	
	

	/**
	 * @return the probabilityMap
	 */
	public synchronized Map<Character, Double> getProbabilityMap() {
		
		return (done?probabilityMap:null);
	}

	/**
	 * @return the unsupported
	 */
	public synchronized Map<Character, Double> getUnsupported() {
		return (done?unsupported:null);
	}

	/**
	 * @return the numOfFiles
	 */
	public synchronized int getNumOfFiles() {
		return numOfFiles;
	}

	/**
	 * @return the numOfDirs
	 */
	public synchronized int getNumOfDirs() {
		return numOfDirs;
	}

	/**
	 * @return the dirName
	 */
	public synchronized String getDirName() {
		return dirName;
	}

	/**
	 * will load all the text files from the directory to the corpus,
	 * 
	 * @param dirNAme
	 *            - the directory to read from
	 * @return String with all the filenames in the corpus separated by a
	 *         newLine Delimiter
	 */
	public String loadCorpusDir() {
		String result = "";
		File files;
		files = new File(dirName);
		if (!files.exists()) {
			return "Directory Not Exist or cannot be opend";
		}
		if (files.isDirectory()) {
			result += (readDir(files));
			result += (System.getProperty("line.separator"));

		} else if (files.isFile()) {
			result += (readFile(files) + "\n");
			result += (System.getProperty("line.separator"));
		} else
			return "not a file of Directory!";
		// calculate probabilty
//		int size = probabilityMap.keySet().size();
		for (Character c : probabilityMap.keySet())
			probabilityMap.put(c, probabilityMap.get(c) / charAmount);
		for (Character c : unsupported.keySet())
			unsupported.put(c, unsupported.get(c)/unsupportedCharAmount);
		return result;
	}

	private String readDir(File files) {
		this.numOfDirs++;
		StringBuilder result = new StringBuilder();
		result.append("reading Directory " + files.getPath() + "..." + System.getProperty("line.separator"));
		File[] fileList = files.listFiles();
		for (File f : fileList) {
			if (f.isDirectory()) {
				if (f.getName().charAt(0) != '.') {
					result.append(readDir(f));
					result.append(System.getProperty("line.separator"));
				}
			} else {
				result.append("readind file:");
				result.append(readFile(f));
				result.append(System.getProperty("line.separator"));
			}
		}
		return result.toString();
	}

	private String readFile(File file) {
		this.numOfFiles++;
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			String line = null;
			while ((line = br.readLine()) != null) {
				for (Character c : line.toCharArray()) {
					/*
					 * if (c != ' '){ Double cVal = probabilityMap.get(c);
					 * probabilityMap.put(c, (cVal == null ? 1 : cVal + 1)); }
					 */
					if (this.probabilityMap.get(c) != null) {
						this.charAmount++;
						this.probabilityMap.put(c, this.probabilityMap.get(c) + 1);
					}
					else if (c != ' '){
//						System.out.println("the char "+c+" is not supported");
						unsupportedCharAmount++;
						this.unsupported.put(c, (this.unsupported.get(c)!=null?this.unsupported.get(c)+1:1));
					}

				}
			}
			return file.getPath();
		} catch (FileNotFoundException e) {
			return "file " + file.getName() + " not found";
		} catch (IOException e) {
			return "I/O error for file " + file.getName();
		}
	}

	
	@Override
	public String toString() {
		System.out.println("toString");
		String ans = "Corpus Statistics:\n";
		double sum =0;
		for (Character c : probabilityMap.keySet()) {
			ans += c + " : " + probabilityMap.get(c) * 100 + "\n";
			sum += probabilityMap.get(c);
		}
		ans += "sum = " + sum+"\n";
		sum =0;
		ans+="unsupported chars: "+unsupported.size()+"\n";
//		for (Character c: unsupported.keySet()){
//			ans += c + " : " + unsupported.get(c) * 100 + "\n";
//			sum += unsupported.get(c);
//		}
//		ans += "sum = " + sum+"\n";
		ans += "END\n";
		ans+="number of chars: "+charAmount+"\n";
		ans+="number of files: "+numOfFiles+"\n";
		ans+="number of dirs: "+numOfDirs+"\n";
		return ans;
	}

}
